package com.xmlt.ui.editors.browsereditor;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;

import com.xmlt.core.template.TemplateException;
import com.xmlt.core.template.TemplateManager;
import com.xmlt.core.template.generation.GenerationTemplate;
import com.xmlt.core.template.generation.IGenerationDescriptor;
import com.xmlt.core.template.instance.Instance;
import com.xmlt.ui.builder.BuilderPlugin;

public class RunGenerationAction extends Action {
	private IEditorPart activeEditor;
	public RunGenerationAction() {
		setText("Generate files");
		setToolTipText("");
	}
	
	public void setActiveEditor(IEditorPart editor) {
		activeEditor = editor;
	}

	@Override
	public void run() {
		IEditorInput input = activeEditor.getEditorInput();
		if (!(input instanceof IFileEditorInput))
			return;
		
		IFile file = ((IFileEditorInput) input).getFile();
		String ref = file.getProjectRelativePath().toString();
		TemplateManager manager = BuilderPlugin.getTemplateManager(file.getProject());
		InstanceVisitor instanceVisitor = new InstanceVisitor(manager);
		try {
			file.getProject().accept(instanceVisitor);
			GenerationTemplate gt = manager.findGenerationTemplate(ref);
			List<Instance> instances = instanceVisitor.getInstances();
			List<IGenerationDescriptor> generationDescriptors = new ArrayList<IGenerationDescriptor>();
			for (Instance ins: instances) {
				generationDescriptors.addAll(gt.getDescriptorsForInstance(ins));
			}

			//IContainer container = file.getParent();
			for (IGenerationDescriptor gd: generationDescriptors) {
				generateFile(gd, file.getProject());
			}
		} catch(Exception rte) {
			MessageDialog.openError(Display.getDefault().getActiveShell(), "Error while generating files", rte.getMessage());
		}
	}
	
	private void generateFile(IGenerationDescriptor descriptor, IProject project) {
		try {
			IResource targetFileResource = project.getFile(descriptor.getPath() + "/" + descriptor.getFileName());
			IFile targetFile = (IFile) targetFileResource.getAdapter(IFile.class);
			
			SectionElementVisitor visitor = new SectionElementVisitor(descriptor.getInstance());
			descriptor.getGeneratingSection().accept(visitor);
			String contents = visitor.getString();
			InputStream contentStream = new ByteArrayInputStream(contents.getBytes());
			if (targetFile.exists()) {
				targetFile.setContents(contentStream, true, true, null);
			} else {
				targetFile.create(contentStream, true, null);
			}
		} catch (TemplateException e) {
			throw new RuntimeException(e);
		} catch (CoreException e) {
			throw new RuntimeException(e);
		}
		
	}
	
	class InstanceVisitor implements IResourceVisitor {
		private List<Instance> instances = new ArrayList<Instance>();
		private TemplateManager templateManager;
		InstanceVisitor(TemplateManager tm) {
			templateManager = tm;
		}
		
		public boolean visit(IResource resource) {
			if (resource.getName().endsWith(".inst")) {
				IFile file = (IFile) resource.getAdapter(IFile.class);
				try {
					Instance ins = templateManager.loadInstance(file.getProjectRelativePath().toString());
					instances.add(ins);
				} catch (TemplateException e) {
				}
			}
			return true;
		}
		
		public List<Instance> getInstances() {
			return instances;
		}
	}
}
